#pragma once
#include <iostream>
#include <pthread.h>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"
namespace RingBufferModule
{
    using namespace LockModule;
    using namespace SemModule;
    template <typename T>
    class RingBuffer
    {
    public:
        RingBuffer(int capacity = 10)
            : _capacity(capacity),
              _p_step(0),
              _c_step(0),
              _datasem(0),
              _spacesem(_capacity)
        {
            _ring.resize(_capacity);
        }
        void Push(const T &in)
        {
            _spacesem.P();
            {
                LockGard plock(_p_lock);
                _ring[_p_step] = in;
                _p_step++;
                _p_step = _p_step % _capacity;
            }
            _datasem.V();
        }
        void Pop(T *out)
        {
            _datasem.P();
            {
                LockGard clock(_c_lock);
                *out = _ring[_c_step];
                _c_step++;
                _c_step = _c_step % _capacity;
            }
            _spacesem.V();
        }
        ~RingBuffer()
        {
            // Sem中的信号析构自动销毁
        }

    private:
        std::vector<T> _ring;
        size_t _capacity;
        int _p_step;
        int _c_step;
        Sem _datasem;
        Sem _spacesem;
        Mutex _c_lock;
        Mutex _p_lock;
    };
}